<?php

namespace addons\shopro\service\order;

use addons\shopro\library\Tree;
use app\admin\model\Admin;
use app\admin\model\shopro\Category;
use app\admin\model\shopro\goods\Goods;
use app\admin\model\shopro\Pay as PayModel;
use app\admin\model\shopro\Refund as RefundModel;
use app\admin\model\shopro\user\User;
use app\admin\model\shopro\order\Order;
use app\admin\model\shopro\order\OrderItem;
use app\admin\model\shopro\order\Action;
use app\admin\model\shopro\goods\Comment;
use app\admin\model\shopro\activity\GiftLog;
use app\admin\model\shopro\activity\Order as ActivityOrderModel;
use app\common\model\letter\Letter;
use app\common\model\letter\LetterContent;
use app\common\model\letter\LetterMailMethod;
use app\common\model\letter\LetterTemplate;
use think\Db;
use think\Log;

class OrderOper
{

    public function __construct()
    {


    }


    /**
     * 订单自动关闭`
     *
     * @param \think\Model $order
     * @param \think\Model|null $user
     * @param string $type
     * @return void
     */
    public function close($order, $user = null, $type = 'user', $msg = '', $ext = [])
    {
        $order->status = Order::STATUS_CLOSED;
        $order->ext = array_merge($order->ext, $ext, ['closed_time' => time()]);      // 关闭时间
        $order->allowField(true)->save();

        Action::add($order, null, $user, $type, ($msg ?: $this->getOperText($type) . '关闭订单'));

        // 订单自动关闭之后 行为 返还用户优惠券，积分
        $data = ['order' => $order];
        \think\Hook::listen('order_close_after', $data);

        return $order;
    }


    /**
     * 订单取消
     *
     * @param object $order
     * @param object $user
     * @param string $type
     * @return object
     */
    public function cancel($order, $user = null, $type = 'user', $msg = '')
    {
        $order->status = Order::STATUS_CANCEL;        // 取消订单
        $order->ext = array_merge($order->ext, ['cancel_time' => time()]);      // 取消时间
        $order->allowField(true)->save();

        Action::add($order, null, $user, $type, ($msg ?: $this->getOperText($type) . '取消订单'));

        // 订单取消，退回库存，退回优惠券积分，等
        $data = ['order' => $order];
        \think\Hook::listen('order_cancel_after', $data);

        return $order;
    }

    /**
     * 订单修改
     *
     * @param object $order
     * @param object $user
     * @param string $type
     * @return object
     */
    public function editOrder($order, $user = null, $type = 'user', $editData = [])
    {
        // 1. 记录原始订单信息
        $originalAmount = $order->pay_fee;

        // 2. 更新订单内容
        if (!empty($editData['new_content']) || !empty($editData['new_nickname']) || !empty($editData['new_signature']) || !empty($editData['new_date'])) {
            $this->updateLetterContent($order, $editData['new_content'], $editData['new_nickname'], $editData['new_signature'], $editData['new_date']);
        }

        if (!empty($editData['new_photos']) || !empty($editData['new_handwriting_photo']) || !empty($editData['new_template_id'])) {
            $this->updateOrderPhotos($order, $editData['new_photos'], $editData['new_handwriting_photo'], $editData['new_template_id']);
        }

        $letter_price = 0;
        $letter_all_total_price = 0;
        $handwriting_photo_price = 0;
        $template_price = 0;
        $option_photo_price = 0;
        $template_infos = '';

        $letter = Letter::where(['order_id' => $order->id])->find();

        // 3. 重新计算订单金额
        if ($order->letter_type == 1) {// 普通信件

            if ($editData['new_photos']) {
                // 计算选择照片费用
                $option_photo_price = calculateLetterCost(['type' => 0, 'option_photo' => $editData['new_photos']])['total_price'];
                $letter_all_total_price = bcadd($letter_all_total_price, $option_photo_price, 2);
            }

            // 计算信件内容费用 明星片无需费用
            if ($letter->method_id > 0 && $letter->method_id != 4) {
                $c_init_params = ['type' => 1, 'method_id' => $letter->method_id];
                // 非手写拍照方式时  需要内容信息
                if ($letter->method_id != 3) {
                    $c_info = LetterContent::where(['letter_id' => $letter['id'], 'uid' => $order->user_id])->find();
                    Log::error('editOrder-非手写拍照方式时  需要内容信息：' . json_encode($c_info));
                    if (!$c_info)
                        error_stop('信件内容不存在');

                    // 信件费用
                    $letter_price = $c_info['content'] ? calculateLetterCost(array_merge($c_init_params, ['characters' => $c_info['content']]))['total_price'] : 0;
                    Log::error('editOrder-信件费用：' . json_encode($letter_price));

                    $letter_all_total_price = bcadd($letter_all_total_price, $letter_price, 2);
//                    var_dump($letter_all_total_price);
                } else {
                    // 手写照片费用
                    $handwriting_photo_price = calculateLetterCost(array_merge($c_init_params, ['handwriting_photo' => $letter->handwriting_photo]))['total_price'];
                    $letter_all_total_price = bcadd($letter_all_total_price, $handwriting_photo_price, 2);
                }

                // 计算模板费用
                $t_info = LetterTemplate::where(['id' => $letter->template_id])->with(['cate'])->find();
                if (!$t_info)
                    error_stop('模板背景不存在');
                $template_price = $t_info['is_pay'] ? $t_info['price'] : 0;
//                var_dump($template_price);
                $letter_all_total_price = bcadd($letter_all_total_price, $template_price, 2);
                $template_infos = $t_info;
            }
        } else {// 明信片
            $c_info = LetterContent::where(['letter_id' => $letter['id'], 'uid' => $order->user_id])->find();
            if (!$c_info || !$c_info['content'])
                error_stop('信件内容不存在或内容为空');

            if ($c_info['letter_id']) {// 存在信件ID
                // 根据信件ID查询信件数据是否已更新了订单ID
                $l_info = Letter::get(['id' => $c_info['letter_id']]);
                Log::error('editOrder-根据信件ID查询信件数据是否已更新了订单ID：' . json_encode($l_info));
                if ($l_info && $l_info['order_id']) {
                    error_stop('信件内容关联订单异常，请联系管理员~');
                }
            }
        }

        $material_infos = json_decode($order->material_infos, true);
        Log::error('editOrder-获取material_infos数据：' . json_encode($material_infos));

        // 累加原材料金额
        $m_total_price = $material_infos ? array_sum(array_column($material_infos, 'm_total_price')) : 0;
        $pay_fee = bcsub($letter_all_total_price, $order->total_discount_fee, 2);
        $pay_fee = $pay_fee < 0 ? 0 : $pay_fee;
        Log::error('editOrder-各种金额1：' . json_encode([
                'order_id' => $order->id,
                'letter_all_total_price' => $letter_all_total_price,
                'total_discount_fee' => $order->total_discount_fee,
                'letter_postage_price' => $order->letter_postage_price,
                'pay_fee' => $pay_fee,
                'material_infos' => $material_infos,
            ]));

        // 累加原来的邮费
        $pay_fee = bcadd($pay_fee, $order->letter_postage_price, 2);
        $pay_fee = bcadd($pay_fee, $m_total_price, 2);
        Log::error('editOrder-各种金额2：' . json_encode([
                'pay_fee' => $pay_fee,
            ]));

        $priceDifference = bcsub($pay_fee, $originalAmount, 2);


        Log::error('editOrder-各种金额3：' . json_encode([
                'priceDifference' => $priceDifference,
            ]));

//        var_dump($pay_fee, $originalAmount, $priceDifference);exit;


        // 更换了模板
        if ($template_infos) {
            $order->template_infos = json_encode($template_infos);
        }

        $order->letter_all_total_price = $letter_all_total_price;
        $order->handwriting_photo_price = $handwriting_photo_price;
        $order->template_price = $template_price;
        $order->letter_price = $letter_price;
        $order->option_photo_price = $option_photo_price;
        $order->goods_amount = $pay_fee;
        $order->order_amount = $pay_fee;
        $order->pay_fee = $pay_fee;
        $order->save();

        (new OrderItem)->save([
            'goods_original_price' => $pay_fee,
            'goods_price' => $pay_fee,
            'pay_fee' => $pay_fee,
        ], ['order_id' => $order->id]);

        // 5. 记录操作日志
        Action::add($order, null, $user, $type, ($editData['msg'] ?? $this->getOperText($type) . '修改订单'));

        $order['is_pay'] = 0;
        // 4. 处理差价
        if ($priceDifference != 0) {
            if ($priceDifference < 0) {// 退款
                // 重新锁定读查询 orderItem
                $item = OrderItem::where('order_id', $order->id)->lock(true)->find();
                if (!$item) {
                    error_stop('订单不存在或不可退款');
                }

                $orderRefund = new OrderRefund($order);
                $admin = Admin::get(2);
                // 处理退款 - 使用绝对值金额
                $refundAmount = abs($priceDifference);
                $orderRefund->refund($item, $refundAmount, $admin, [
                    'refund_type' => 'back',
                    'remark' => '修改订单产生差价退回'
                ]);
                $item->refund_status = 0;
                $item->save();
            } else {// 需要支付新的金额
//                // 更新原订单的remain_pay_fee字段
//                $order->remain_pay_fee = $priceDifference;
//                $order->save();
                $order = $this->createSupplementOrder($order, $user, $priceDifference);
            }
        }

        return $order;
    }

    protected function createSupplementOrder($order, $user, $priceDifference)
    {
        // 1. 准备订单数据
        $orderData = [
            'type' => 'xj_goods', // 就用原订单类型
//            'type' => 'cj_goods', // 差价订单类型
            'user_id' => $user->id,
            'original_order_id' => $order->id, // 关联原订单
            'goods_original_amount' => $priceDifference,
            'goods_amount' => $priceDifference,
            'order_amount' => $priceDifference,
            'pay_fee' => $priceDifference,
            'remain_pay_fee' => $priceDifference,
            'original_pay_fee' => $priceDifference,
            'status' => 'unpaid',
            'createtime' => time(),
            'updatetime' => time(),
            'is_letter_order' => $order->is_letter_order,
            'letter_type' => $order->letter_type,
            'ext' => json_encode([
                'source_order_sn' => $order->order_sn,
                'source_order_id' => $order->id,
                'created_type' => 'order_modify'
            ])
        ];

        // 2. 生成订单号
        $orderData['order_sn'] = get_sn($user->id, 'CD'); // CD表示补差价订单

        // 3. 创建订单
        $supplementOrderId = Db::name('shopro_order')->insertGetId($orderData);
        if (!$supplementOrderId) {
            throw new \Exception('补差价订单创建失败');
        }

        $goods = Db::name('shopro_goods')->where(['id' => 142])->find();

        // 4. 创建订单商品项
        $orderItemData = [
            'order_id' => $supplementOrderId,
            'user_id' => $user->id,
            'goods_id' => $goods['id'], // 补差价商品ID
            'goods_type' => $goods['type'],
            'goods_title' => '订单' . $order['order_sn'] . '补差价',
            'goods_image' => $goods['image'],
            'goods_original_price' => $priceDifference,
            'goods_price' => $priceDifference,
            'goods_num' => 1,
            'pay_fee' => $priceDifference,
            'createtime' => time(),
            'updatetime' => time()
        ];

        $orderItemId = Db::name('shopro_order_item')->insertGetId($orderItemData);
        if (!$orderItemId) {
            throw new \Exception('补差价订单商品创建失败');
        }

        // 5. 返回订单信息
        return [
            'order_id' => $supplementOrderId,
            'order_sn' => $orderData['order_sn'],
            'amount' => $priceDifference,
            'is_pay' => 1,
            'pay_url' => '' // 实际业务中需要生成支付链接
        ];
    }

    /**
     * 更新信件内容
     */
    protected function updateLetterContent($order, $newContent, $newNickname, $newSignature, $newDate)
    {
        Log::error("updateLetterContent1：" . json_encode([
                'order' => $order,
                'newContent' => $newContent,
                'newNickname' => $newNickname,
                'newSignature' => $newSignature,
                'newDate' => $newDate,
            ]));
        $letter = Letter::where(['order_id' => $order->id])->find();
        Log::error("updateLetterContent2：" . json_encode($letter));
        if ($letter) {
            $letterContent = LetterContent::where(['letter_id' => $letter['id'], 'uid' => $order->user_id])->find();
            Log::error("updateLetterContent3：" . json_encode($letterContent));
            if ($letterContent) {
                $letterContent->old_content = $letterContent['content'];
                $letterContent->content = $newContent;
                $letterContent->old_nickname = $letterContent['nickname'];
                $letterContent->nickname = $newNickname;
                $letterContent->old_signature = $letterContent['signature'];
                $letterContent->signature = $newSignature;
                $letterContent->old_date = $letterContent['date'];
                $letterContent->date = $newDate;
                $letterContent->save();
            }
        }

    }

    /**
     * 更新订单照片
     */
    protected function updateOrderPhotos($order, $newPhotos, $newHandwritingPhotos, $newTemplateId)
    {
        Log::error("updateOrderPhotos1：" . json_encode([
                'order' => $order,
                'newPhotos' => $newPhotos,
                'newHandwritingPhotos' => $newHandwritingPhotos,
                'newTemplateId' => $newTemplateId,
            ]));

        $letter = Letter::where(['order_id' => $order->id])->find();
        Log::error("updateOrderPhotos2：" . json_encode($letter));
        if ($letter) {
            $letter->old_photo = $letter['photo'];
            $letter->photo = $newPhotos;
            if ($letter->method_id == 3) {// 信件是手写拍照的  才更新
                $letter->old_handwriting_photo = $letter['handwriting_photo'];
                $letter->handwriting_photo = $newHandwritingPhotos;
            }
            $letter->old_template_id = $letter['template_id'];
            $letter->template_id = $newTemplateId;
            $letter->save();
        }

    }


    /**
     * 申请全额退款
     *
     * @param object $order
     * @param object $user
     * @param string $type
     * @return object
     */
    public function applyRefund($order, $user, $type = 'user')
    {
        $items = OrderItem::where('order_id', $order->id)->lock(true)->select();

        foreach ($items as $key => $item) {
            if (in_array($item['refund_status'], [
                OrderItem::REFUND_STATUS_AGREE,
                OrderItem::REFUND_STATUS_COMPLETED,
            ])) {
                error_stop('订单有退款，不可申请');
            }

            if ($item['dispatch_status'] != OrderItem::DISPATCH_STATUS_NOSEND) {
                error_stop('订单已发件，不可申请');
            }
        }

        $order->apply_refund_status = Order::APPLY_REFUND_STATUS_APPLY;        // 申请退款
        $order->ext = array_merge($order->ext, ['apply_refund_time' => time()]);      // 申请时间
        $order->save();

        Action::add($order, null, $user, $type, $this->getOperText($type) . '申请全额退款');

        // 订单申请全额退款
        $data = ['order' => $order, 'user' => $user];
        \think\Hook::listen('order_apply_refund_after', $data);

        return $order;
    }


    /**
     * 确认收货
     *
     * @param object $order
     * @param array $itemIds
     * @param object|null $user
     * @param string $type
     * @return object
     */
    public function confirm($order, $itemIds = [], $user = null, $type = 'user')
    {
        $items = OrderItem::canConfirm()->where('order_id', $order->id)->where(function ($query) use ($itemIds) {
            if ($itemIds) {
                // 只确认收货传入的 ids
                $query->whereIn('id', $itemIds);
            }
        })->lock(true)->select();

        if (!$items) {
            error_stop('订单已确认收货，请不要重复确认收货');
        }

        foreach ($items as $item) {
            $item->ext = array_merge($item->ext, ['confirm_time' => time()]);
            $item->dispatch_status = OrderItem::DISPATCH_STATUS_GETED;        // 确认收货
            $item->save();

            Action::add($order, $item, $user, $type, $this->getOperText($type) . '确认收货');

            // 订单确认收货后
            $data = ['order' => $order, 'item' => $item];
            \think\Hook::listen('order_confirm_after', $data);
        }
        $order->status = 'completed';// 确认收货
        return $order;
    }


    /**
     * 拒收收货
     *
     * @param object $order
     * @param array $itemIds
     * @param object|null $user
     * @param string $type
     * @return object
     */
    public function refuse($order, $user = null, $type = 'user')
    {
        $items = OrderItem::canConfirm()->where('order_id', $order->id)->lock(true)->select();

        if (!$items) {
            error_stop('没有可拒收的商品');
        }

        foreach ($items as $item) {
            $item->ext = array_merge($item->ext, ['refuse_time' => time()]);
            $item->dispatch_status = OrderItem::DISPATCH_STATUS_REFUSE;        // 拒收
            $item->save();

            Action::add($order, $item, $user, $type, $this->getOperText($type) . '操作，用户拒绝收货');
        }

        // 订单拒收后事件
        $data = ['order' => $order];
        \think\Hook::listen('order_refuse_after', $data);

        return $order;
    }


    /**
     * 评价 (根据 comments 中的数据进行评价， 可以之评价一个（系统自动评价时候）)
     *
     * @param object $order
     * @param object|null $user
     * @param string $type
     * @return object
     */
    public function comment($order, $comments, $user = null, $type = 'user')
    {
        // 评价的orderItem id
        $comments = array_column($comments, null, 'item_id');
        $itemIds = array_keys($comments);

        $items = OrderItem::canComment()->where('order_id', $order->id)->lock(true)->select();

        if (!$items) {
            if ($type == 'system') {
                return $order;      // 系统自动评价时检测到用户已经自己评价，这里直接返回，不抛出异常
            }
            error_stop('订单已评价，请不要重复评价');
        }

        $orderConfig = sheep_config('shop.order');
        $orderUser = User::get($order->user_id);

        foreach ($items as $item) {
            if (!in_array($item['id'], $itemIds)) {
                // 不在本次评价列表
                continue;
            }
            $comment = $comments[$item['id']] ?? [];

            $status = 'normal';
            if (isset($orderConfig['comment_check']) && $orderConfig['comment_check'] && $type != 'system') {
                // 需要检查，并且不是系统自动评价
                $status = 'hidden';
            }

            Comment::create([
                'goods_id' => $item->goods_id,
                'order_id' => $order->id,
                'order_item_id' => $item->id,
                'user_id' => $order->user_id,
                'user_nickname' => $orderUser ? $orderUser->nickname : null,
                'user_avatar' => $orderUser ? $orderUser->avatar : null,
                'level' => $comment['level'] ?? 5,
                'content' => $comment['content'] ?? ($orderConfig['auto_comment_content'] ?? '用户默认好评'),
                'images' => $comment['images'] ?? [],
                'status' => $status
            ]);

            $item->ext = array_merge($item->ext, ['comment_time' => time()]);
            $item->comment_status = OrderItem::COMMENT_STATUS_OK;        // 评价
            $item->save();

            Action::add($order, $item, $user, $type, $this->getOperText($type) . '评价完成');

            // 订单评价后
            $data = ['order' => $order, 'item' => $item, 'user' => $user];
            \think\Hook::listen('order_comment_after', $data);
        }

        return $order;
    }


    /**
     * 删除订单
     *
     * @param object $order
     * @param object|null $user
     * @param string $type
     * @return void
     */
    public function delete($order, $user = null, $type = 'user')
    {
        $order->delete();        // 删除订单

        Action::add($order, null, $user, 'user', '用户删除订单');
    }


    /**
     * 存储活动信息
     *
     * @param \think\Model $order
     * @param array $result
     * @return void
     */
    public function addActivityOrder($order)
    {
        $ext = $order->ext;
        $items = $order->items;
        $goodsIds = array_column($items, 'goods_id');

        $model = new ActivityOrderModel();
        $model->order_id = $order->id;
        $model->user_id = $order->user_id;
        $model->activity_id = $order->activity_id;
        $model->activity_title = $ext['activity_title'] ?? null;
        $model->activity_type = $ext['activity_type'] ?? null;
        $model->pay_fee = $order->pay_fee;
        $model->goods_amount = $order->goods_amount;
        $model->discount_fee = $ext['activity_discount_amount'] ?? 0;       // 普通商品总额和活动时商品总额的差
        $model->goods_ids = join(',', $goodsIds);

        $model->save();
    }


    /**
     * 存储促销信息
     *
     * @param \think\Model $order
     * @param array $result
     * @return void
     */
    public function addPromosOrder($order)
    {
        $ext = $order->ext;
        $promoInfos = $ext['promo_infos'] ?? [];

        foreach ($promoInfos as $key => $info) {
            $model = new ActivityOrderModel();
            $model->order_id = $order->id;
            $model->user_id = $order->user_id;
            $model->activity_id = $info['activity_id'];
            $model->activity_title = $info['activity_title'];
            $model->activity_type = $info['activity_type'];
            $model->pay_fee = $order->pay_fee;
            $model->goods_amount = $info['promo_goods_amount'];

            $model->discount_fee = 0;
            if (in_array($info['activity_type'], ['full_reduce', 'full_discount', 'free_shipping'])) {
                $model->discount_fee = $info['promo_discount_money'];
            } else if ($info['activity_type'] == 'full_gift') {
                // 这里设置为 0，等支付成功之后补充
                $model->discount_fee = 0;
            }

            $model->goods_ids = join(',', $info['goods_ids']);
            $rules = [
                'rule_type' => $info['rule_type'],
                'discount_rule' => $info['discount_rule'],
            ];
            if ($info['activity_type'] == 'full_gift') {
                $rules['limit_num'] = $info['limit_num'] ?? 0;
                $rules['event'] = $info['event'] ?? 0;
            }
            $currentExt['rules'] = $rules;
            $model->ext = $currentExt;
            $model->save();
        }
    }


    /**
     * 将活动订单标记为已支付
     *
     * @param [type] $order
     * @return void
     */
    public function activityOrderPaid($order)
    {
        $activityOrders = ActivityOrderModel::where('order_id', $order->id)->select();

        foreach ($activityOrders as $activityOrder) {
            if ($activityOrder->activity_type == 'full_gift') {
                $value_money = GiftLog::where('activity_id', $activityOrder->activity_id)
                    ->where('order_id', $activityOrder->order_id)
                    ->where('user_id', $activityOrder->user_id)
                    ->whereIn('type', ['money', 'coupon'])        // 这里只算 赠送的余额，和优惠券（不算积分，和赠送商品的价值）
                    ->sum('value');

                $activityOrder->discount_fee = $value_money;      // 补充赠送的价值
            } else if (in_array($activityOrder->activity_type, ['groupon', 'groupon_ladder'])) {
                $ext = $order->ext;
                $currentExt['buy_type'] = $ext['buy_type'] ?? '';
                $currentExt['groupon_id'] = $ext['groupon_id'] ?? 0;        // 开团时候，支付之后才会有 groupon_id
                $activityOrder->ext = $currentExt;
            }

            $activityOrder->status = ActivityOrderModel::STATUS_PAID;
            $activityOrder->save();
        }
    }


    /**
     * 根据 oper_type 获取对应的用户
     */
    private function getOperText($oper_type)
    {
        switch ($oper_type) {
            case 'user':
                $oper_text = '用户';
                break;
            case 'admin':
                $oper_text = '管理员';
                break;
            case 'system':
                $oper_text = '系统自动';
                break;
            default :
                $oper_text = '系统自动';
                break;
        }

        return $oper_text;
    }
}
